/**
 * Created by zhangguoyu on 16/5/5.
 */

var Oop = require('../lang/Oop');
var util = require('util');
var LogUtils = require('../utils/log/LogUtils');
var Utils = require('../utils/Utils');
var co = require('co');
var events = require('events');

var BaseLogsResolver = Utils.extend(function (model) {
  this.$resolvedModel = model;
}, Oop);

BaseLogsResolver.prototype.resolvedModel = function () {
  return this.$resolvedModel;
};

BaseLogsResolver.prototype.prepareResolve = function (model) {
  throw new Error('必须实现 prepareResolve 方法');
};

BaseLogsResolver.prototype.onResolving = function () {
  this.emit.apply(this, ['onresolving', this].concat(Utils.toArray(arguments)))
};

BaseLogsResolver.prototype.onCompletion = function (resolvedResult) {
  this.emit('oncompletion', this, resolvedResult);
};

BaseLogsResolver.prototype.resolve = function (func) {
  var self = this;
  return new Promise(function (resolve, reject) {
    var model = self.resolvedModel();
    co(function * () {

      var count = yield model.$manager.count();
      if (count <= 0) {
        var res = self.onCompletion([]);
        if (Utils.isPromise(res)) {
          var t = yield res;
          if (t !== undefined) {
            res = t;
          }
        }
        if (Utils.isFunction(func)) {
          Utils.callFunc(func, self, undefined, res);
        }
        resolve(res);
        return;
      }

      var querySet = yield model.$manager.mapReduce(self.prepareResolve(model))
        .then(function (mapReduceResult) {
          var model = mapReduceResult.model;
          return model.$manager.all();
        }, function (err) {
          LogUtils.error(err.toString());
          if (Utils.isFunction(func)) {
            Utils.callFunc(func, self, err);
          }
          reject(err);
        });

      var resultSet = undefined;
      if (querySet && querySet.length) {
        var len = querySet.length;
        resultSet = new Array(len);
        for (var i = 0; i < len; i++) {
          var queryItem = querySet[i];
          var args = queryItem._id.split('|');
          args.push(queryItem.value);
          var resolveResult = self.onResolving.apply(self, args);
          if (Utils.isPromise(resolveResult)) {
            resolveResult = yield resolveResult;
          }
          if (resolveResult === undefined) {
            resolveResult = queryItem;
          }
          resultSet[i] = resolveResult
        }
        var tempResult = self.onCompletion(resultSet);
        if (tempResult !== undefined) {
          resultSet = tempResult;
        }
        if (Utils.isPromise(resultSet)) {
          resultSet = yield resultSet;
        }
        if (Utils.isFunction(func)) {
          Utils.callFunc(func, self, undefined, resultSet);
        }
        resolve(resultSet || []);
      }
    }).catch(function (err) {
      LogUtils.error(err.toString());
      if (Utils.isFunction(func)) {
        Utils.callFunc(func, self, err);
      }
      reject(err);
    });
  });
};

module.exports = BaseLogsResolver;

